import { Service } from '../types/index.js';
import { getStorage, setStorage } from '../utils/storage.js';

/**
 * 通知类型枚举
 */
export const NotificationType = {
  INFO: 'info',
  SUCCESS: 'success',
  WARNING: 'warning',
  ERROR: 'error',
  CONFIRM: 'confirm',
  PROMPT: 'prompt',
  LOADING: 'loading'
};

/**
 * 通知位置枚举
 */
export const NotificationPosition = {
  TOP_RIGHT: 'top-right',
  TOP_LEFT: 'top-left',
  BOTTOM_RIGHT: 'bottom-right',
  BOTTOM_LEFT: 'bottom-left',
  TOP_CENTER: 'top-center',
  BOTTOM_CENTER: 'bottom-center',
  CENTER: 'center'
};

/**
 * 通知服务
 * 提供统一的消息通知功能，包括顶部通知、确认对话框、全局消息等
 */
class NotificationService extends Service {
  constructor(container, options = {}) {
    super(container, options);
    
    // 默认配置
    this.config = {
      // 通知配置
      defaultDuration: 3000,
      maxVisible: 5,
      position: NotificationPosition.TOP_RIGHT,
      zIndex: 2050,
      
      // 确认对话框配置
      confirmDefaultTitle: '确认操作',
      confirmOkText: '确定',
      confirmCancelText: '取消',
      
      // 加载配置
      loadingDefaultText: '处理中...',
      
      // 震动提示
      enableVibrate: false,
      vibratePattern: [50, 50],
      
      // 声音提示
      enableSound: false,
      
      // 是否记录通知历史
      enableHistory: true,
      
      // 历史记录限制数量
      maxHistoryCount: 100,
      
      ...(this.container.config?.admin?.notification || {})
    };
    
    // 活跃通知列表
    this.activeNotifications = [];
    
    // 通知历史记录
    this.notificationHistory = [];
    
    // 加载提示的引用
    this.loadingInstance = null;
    
    // 事件监听器
    this.listeners = new Map();
    
    // 初始化历史记录
    this.initHistory();
  }

  /**
   * 启动服务
   */
  async boot() {
    this.logger.info('Notification service booted');
  }

  /**
   * 关闭服务
   */
  async shutdown() {
    // 关闭所有活跃通知
    this.closeAll();
    this.listeners.clear();
    this.logger.info('Notification service shutdown');
  }

  /**
   * 初始化历史记录
   */
  initHistory() {
    if (this.config.enableHistory) {
      const savedHistory = getStorage('notification_history');
      if (savedHistory) {
        try {
          this.notificationHistory = JSON.parse(savedHistory);
        } catch (error) {
          this.logger.warn('Failed to load notification history:', error);
          this.notificationHistory = [];
        }
      }
    }
  }

  /**
   * 保存历史记录
   */
  saveHistory() {
    if (this.config.enableHistory) {
      // 限制历史记录数量
      if (this.notificationHistory.length > this.config.maxHistoryCount) {
        this.notificationHistory = this.notificationHistory.slice(
          this.notificationHistory.length - this.config.maxHistoryCount
        );
      }
      
      setStorage('notification_history', JSON.stringify(this.notificationHistory));
    }
  }

  /**
   * 添加通知到历史记录
   * @param {Object} notification 通知对象
   */
  addToHistory(notification) {
    if (this.config.enableHistory && notification.type !== NotificationType.LOADING) {
      const historyItem = {
        id: notification.id,
        type: notification.type,
        title: notification.title,
        message: notification.message,
        timestamp: new Date().toISOString()
      };
      
      this.notificationHistory.unshift(historyItem);
      this.saveHistory();
    }
  }

  /**
   * 触发震动
   */
  vibrate() {
    if (this.config.enableVibrate && navigator.vibrate) {
      navigator.vibrate(this.config.vibratePattern);
    }
  }

  /**
   * 播放声音
   * @param {string} type 通知类型
   */
  playSound(type) {
    if (this.config.enableSound) {
      // 实际项目中可以根据不同类型播放不同的声音
      // 这里仅作为示例
      // const audio = new Audio(`/sounds/${type}.mp3`);
      // audio.play().catch(e => this.logger.warn('Failed to play sound:', e));
    }
  }

  /**
   * 创建通知ID
   * @returns {string} 唯一ID
   */
  createNotificationId() {
    return `notification_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * 基础通知方法
   * @param {string} type 通知类型
   * @param {string|Object} options 通知选项或消息内容
   * @returns {Object} 通知实例
   */
  notify(type, options) {
    // 统一处理选项
    const notificationOptions = typeof options === 'string' 
      ? { message: options }
      : { ...options };
    
    // 创建通知对象
    const notification = {
      id: this.createNotificationId(),
      type,
      title: notificationOptions.title || '',
      message: notificationOptions.message || '',
      duration: notificationOptions.duration ?? this.config.defaultDuration,
      position: notificationOptions.position || this.config.position,
      onClose: notificationOptions.onClose,
      onShow: notificationOptions.onShow,
      onClick: notificationOptions.onClick,
      icon: notificationOptions.icon,
      customClass: notificationOptions.customClass,
      showClose: notificationOptions.showClose !== false,
      dangerouslyUseHTMLString: notificationOptions.dangerouslyUseHTMLString || false,
      offset: notificationOptions.offset || 0,
      appendTo: notificationOptions.appendTo || document.body,
      timestamp: Date.now()
    };
    
    // 触发震动和声音
    if (notificationOptions.enableVibrate !== false) {
      this.vibrate();
    }
    
    if (notificationOptions.enableSound !== false) {
      this.playSound(type);
    }
    
    // 添加到活跃通知列表
    this.activeNotifications.push(notification);
    
    // 限制同时显示的通知数量
    if (this.activeNotifications.length > this.config.maxVisible) {
      const removedNotification = this.activeNotifications.shift();
      this.close(removedNotification.id);
    }
    
    // 添加到历史记录
    this.addToHistory(notification);
    
    // 触发通知事件
    this.emit('notificationCreated', notification);
    
    // 显示通知
    this.renderNotification(notification);
    
    // 设置自动关闭（如果有持续时间）
    if (notification.duration > 0 && type !== NotificationType.LOADING) {
      notification.timer = setTimeout(() => {
        this.close(notification.id);
      }, notification.duration);
    }
    
    return notification;
  }

  /**
   * 渲染通知（占位方法，实际项目中需要实现具体的DOM操作）
   * @param {Object} notification 通知对象
   */
  renderNotification(notification) {
    // 这里是渲染通知的占位实现
    // 实际项目中，应该使用Vue组件或其他方式渲染通知
    this.logger.info(`Rendering notification: ${notification.id}`, notification);
    
    // 模拟通知显示完成
    if (notification.onShow) {
      setTimeout(() => notification.onShow(notification), 10);
    }
    
    // 模拟通知被点击
    notification.click = () => {
      if (notification.onClick) {
        notification.onClick(notification);
      }
      this.close(notification.id);
    };
  }

  /**
   * 显示信息通知
   * @param {string|Object} options 通知选项或消息内容
   * @returns {Object} 通知实例
   */
  info(options) {
    return this.notify(NotificationType.INFO, options);
  }

  /**
   * 显示成功通知
   * @param {string|Object} options 通知选项或消息内容
   * @returns {Object} 通知实例
   */
  success(options) {
    return this.notify(NotificationType.SUCCESS, options);
  }

  /**
   * 显示警告通知
   * @param {string|Object} options 通知选项或消息内容
   * @returns {Object} 通知实例
   */
  warning(options) {
    return this.notify(NotificationType.WARNING, options);
  }

  /**
   * 显示错误通知
   * @param {string|Object} options 通知选项或消息内容
   * @returns {Object} 通知实例
   */
  error(options) {
    return this.notify(NotificationType.ERROR, options);
  }

  /**
   * 显示确认对话框
   * @param {string|Object} options 对话框选项或消息内容
   * @returns {Promise} Promise对象，resolve表示确认，reject表示取消
   */
  confirm(options) {
    return new Promise((resolve, reject) => {
      const confirmOptions = typeof options === 'string' 
        ? { message: options }
        : { ...options };
      
      // 创建确认对话框配置
      const dialogOptions = {
        ...confirmOptions,
        type: NotificationType.CONFIRM,
        title: confirmOptions.title || this.config.confirmDefaultTitle,
        okText: confirmOptions.okText || this.config.confirmOkText,
        cancelText: confirmOptions.cancelText || this.config.confirmCancelText,
        position: NotificationPosition.CENTER,
        duration: 0, // 确认框不自动关闭
        onOk: () => {
          if (confirmOptions.onOk) {
            confirmOptions.onOk();
          }
          resolve();
        },
        onCancel: () => {
          if (confirmOptions.onCancel) {
            confirmOptions.onCancel();
          }
          reject();
        }
      };
      
      // 创建对话框通知
      const notification = this.notify(NotificationType.CONFIRM, dialogOptions);
      
      // 模拟确认对话框
      this.logger.info(`Rendering confirm dialog: ${notification.id}`, notification);
      
      // 提供关闭方法
      notification.close = () => this.close(notification.id);
      notification.ok = () => {
        dialogOptions.onOk();
        this.close(notification.id);
      };
      notification.cancel = () => {
        dialogOptions.onCancel();
        this.close(notification.id);
      };
    });
  }

  /**
   * 显示提示对话框
   * @param {string|Object} options 对话框选项或消息内容
   * @returns {Promise} Promise对象，resolve表示确认并返回输入值，reject表示取消
   */
  prompt(options) {
    return new Promise((resolve, reject) => {
      const promptOptions = typeof options === 'string' 
        ? { message: options }
        : { ...options };
      
      // 创建提示对话框配置
      const dialogOptions = {
        ...promptOptions,
        type: NotificationType.PROMPT,
        title: promptOptions.title || this.config.confirmDefaultTitle,
        okText: promptOptions.okText || this.config.confirmOkText,
        cancelText: promptOptions.cancelText || this.config.confirmCancelText,
        position: NotificationPosition.CENTER,
        duration: 0,
        inputType: promptOptions.inputType || 'text',
        inputPlaceholder: promptOptions.inputPlaceholder || '',
        inputValue: promptOptions.inputValue || '',
        inputValidator: promptOptions.inputValidator,
        onOk: (value) => {
          if (promptOptions.onOk) {
            promptOptions.onOk(value);
          }
          resolve(value);
        },
        onCancel: () => {
          if (promptOptions.onCancel) {
            promptOptions.onCancel();
          }
          reject();
        }
      };
      
      // 创建对话框通知
      const notification = this.notify(NotificationType.PROMPT, dialogOptions);
      
      // 模拟提示对话框
      this.logger.info(`Rendering prompt dialog: ${notification.id}`, notification);
      
      // 提供关闭方法
      notification.close = () => this.close(notification.id);
      notification.ok = (value) => {
        dialogOptions.onOk(value);
        this.close(notification.id);
      };
      notification.cancel = () => {
        dialogOptions.onCancel();
        this.close(notification.id);
      };
    });
  }

  /**
   * 显示加载提示
   * @param {string|Object} options 加载提示选项或文本内容
   * @returns {Object} 加载提示实例
   */
  loading(options = {}) {
    // 如果已有加载提示，则先关闭
    if (this.loadingInstance) {
      this.close(this.loadingInstance.id);
    }
    
    const loadingOptions = typeof options === 'string' 
      ? { message: options }
      : { ...options };
    
    // 创建加载提示配置
    const loadOptions = {
      ...loadingOptions,
      type: NotificationType.LOADING,
      message: loadingOptions.message || this.config.loadingDefaultText,
      position: loadingOptions.position || NotificationPosition.CENTER,
      duration: 0, // 加载提示不自动关闭
      showClose: false
    };
    
    // 创建加载提示通知
    this.loadingInstance = this.notify(NotificationType.LOADING, loadOptions);
    
    // 模拟加载提示
    this.logger.info(`Rendering loading: ${this.loadingInstance.id}`, this.loadingInstance);
    
    return this.loadingInstance;
  }

  /**
   * 关闭加载提示
   */
  closeLoading() {
    if (this.loadingInstance) {
      this.close(this.loadingInstance.id);
      this.loadingInstance = null;
    }
  }

  /**
   * 关闭指定通知
   * @param {string} id 通知ID
   * @returns {boolean} 是否成功关闭
   */
  close(id) {
    const index = this.activeNotifications.findIndex(notification => notification.id === id);
    
    if (index !== -1) {
      const notification = this.activeNotifications[index];
      
      // 清除定时器
      if (notification.timer) {
        clearTimeout(notification.timer);
      }
      
      // 移除通知
      this.activeNotifications.splice(index, 1);
      
      // 触发关闭回调
      if (notification.onClose) {
        notification.onClose(notification);
      }
      
      // 触发关闭事件
      this.emit('notificationClosed', notification);
      
      this.logger.info(`Notification closed: ${id}`);
      return true;
    }
    
    return false;
  }

  /**
   * 关闭所有通知
   */
  closeAll() {
    const ids = this.activeNotifications.map(notification => notification.id);
    ids.forEach(id => this.close(id));
    
    // 确保加载提示也被关闭
    if (this.loadingInstance) {
      this.closeLoading();
    }
    
    this.logger.info('All notifications closed');
  }

  /**
   * 获取活跃通知数量
   * @returns {number} 活跃通知数量
   */
  getActiveCount() {
    return this.activeNotifications.length;
  }

  /**
   * 获取历史通知
   * @param {number} limit 限制数量
   * @returns {Array} 历史通知列表
   */
  getHistory(limit) {
    if (limit) {
      return this.notificationHistory.slice(0, limit);
    }
    return [...this.notificationHistory];
  }

  /**
   * 清空历史记录
   */
  clearHistory() {
    this.notificationHistory = [];
    this.saveHistory();
    this.logger.info('Notification history cleared');
  }

  /**
   * 注册事件监听器
   * @param {string} event 事件名称
   * @param {function} listener 事件监听器
   */
  on(event, listener) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, []);
    }
    this.listeners.get(event).push(listener);
  }

  /**
   * 移除事件监听器
   * @param {string} event 事件名称
   * @param {function} listener 事件监听器
   */
  off(event, listener) {
    if (this.listeners.has(event)) {
      const listeners = this.listeners.get(event);
      const index = listeners.indexOf(listener);
      if (index > -1) {
        listeners.splice(index, 1);
      }
    }
  }

  /**
   * 触发事件
   * @param {string} event 事件名称
   * @param  {...any} args 事件参数
   */
  emit(event, ...args) {
    if (this.listeners.has(event)) {
      for (const listener of this.listeners.get(event)) {
        try {
          listener(...args);
        } catch (error) {
          this.logger.error(`Error in notification event listener for ${event}:`, error);
        }
      }
    }
  }

  /**
   * 包装异步操作，自动显示加载提示
   * @param {Function} fn 异步函数
   * @param {string|Object} loadingOptions 加载提示选项
   * @returns {Promise} 原始函数的Promise结果
   */
  async withLoading(fn, loadingOptions = {}) {
    try {
      // 显示加载提示
      const loading = this.loading(loadingOptions);
      
      // 执行异步函数
      const result = await fn();
      
      // 关闭加载提示
      this.closeLoading();
      
      return result;
    } catch (error) {
      // 关闭加载提示
      this.closeLoading();
      
      // 可以根据需要自动显示错误通知
      if (error.showErrorNotification !== false) {
        this.error(error.message || '操作失败');
      }
      
      // 重新抛出错误
      throw error;
    }
  }

  /**
   * 配置通知服务
   * @param {Object} config 新配置
   */
  configure(config) {
    this.config = { ...this.config, ...config };
    this.logger.info('Notification service configured', this.config);
  }
}

export default NotificationService;